package com.atguigu.gmall.common.service;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.entity.GmallCorrelationData;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.UUID;

/**
 * @author 李旭
 * @date 2021/12/3 10:15
 * @Description:
 *
 *   自定义的实现类
 *      封装发消息的步骤的实现类
 *
 */
@SuppressWarnings("all")
@Component
public class RabbitService {


    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RedisTemplate redisTemplate;

    //MQ的消息的散列类型的Key
    public static final String RABBITMQ_RETRYMESSAGE  = "rabbitmq:retryMessage";

    //发消息
    public void sendMessage(String exchange,String routingKey,Object msg){
        //关联数据   交换机应答的时候 将关联数据对象传递给交换机应答方法 形参
        GmallCorrelationData gmallCorrelationData = new GmallCorrelationData();
        //交换机
        gmallCorrelationData.setExchange(exchange);
        //路由Key
        gmallCorrelationData.setRoutingKey(routingKey);
        //消息
        gmallCorrelationData.setMessage(msg);
        //UUID
        String uuid = UUID.randomUUID().toString();
        gmallCorrelationData.setId(uuid);
        System.out.println(uuid);
        //将关联数据对象放入 缓存Redis   上上策
        redisTemplate.opsForHash().put(RABBITMQ_RETRYMESSAGE,uuid,
                                         JSONObject.toJSONString(gmallCorrelationData));
        //发消息
        rabbitTemplate.convertAndSend(
                exchange,routingKey,msg,(message) -> {
                    message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.fromInt(2));
                    return message;
                },gmallCorrelationData);

    }

    //发送基于死信延迟消息
    public void sendDeadLetterMessage(String exchange,String routingKey,Object msg,int delayTime){
        //关联数据   交换机应答的时候 将关联数据对象传递给交换机应答方法 形参
        GmallCorrelationData gmallCorrelationData = new GmallCorrelationData();
        //交换机
        gmallCorrelationData.setExchange(exchange);
        //路由Key
        gmallCorrelationData.setRoutingKey(routingKey);
        //消息
        gmallCorrelationData.setMessage(msg);
        // 是否是延迟消息  是
        gmallCorrelationData.setDelayDeadLetter(true);
        //延迟的时间
        gmallCorrelationData.setDelayTime(delayTime);
        //UUID
        String uuid = UUID.randomUUID().toString();
        gmallCorrelationData.setId(uuid);
        System.out.println(uuid);
        //将关联数据对象放入 缓存Redis   上上策
        redisTemplate.opsForHash().put(RABBITMQ_RETRYMESSAGE,uuid,
                JSONObject.toJSONString(gmallCorrelationData));
        //发消息(基于死信的延迟消息)
        rabbitTemplate.convertAndSend(
                exchange,routingKey,msg,(message) -> {
                    //消息的属性
                    //消息的持久化属性
                    message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.fromInt(2));
                    //消息的延迟的时间的属性    毫秒
                    message.getMessageProperties().setExpiration(String.valueOf(delayTime*1000));
                    System.out.println("基于死信发消息的时间是:" + new Date());
                    return message;
                },gmallCorrelationData);

    }
    //发消息 基于插件的延迟消息
    public void sendDelayedMessage(String exchange, String routingKey, Object msg, int delayTime) {
//关联数据   交换机应答的时候 将关联数据对象传递给交换机应答方法 形参
        GmallCorrelationData gmallCorrelationData = new GmallCorrelationData();
        //交换机
        gmallCorrelationData.setExchange(exchange);
        //路由Key
        gmallCorrelationData.setRoutingKey(routingKey);
        //消息
        gmallCorrelationData.setMessage(msg);
        // 是否是延迟消息  是
        gmallCorrelationData.setDelay(true);
        //延迟的时间
        gmallCorrelationData.setDelayTime(delayTime);
        //UUID
        String uuid = UUID.randomUUID().toString();
        gmallCorrelationData.setId(uuid);
        System.out.println(uuid);
        //将关联数据对象放入 缓存Redis   上上策
        redisTemplate.opsForHash().put(RABBITMQ_RETRYMESSAGE,uuid,
                JSONObject.toJSONString(gmallCorrelationData));
        //发消息(基于死信的延迟消息)
        rabbitTemplate.convertAndSend(
                exchange,routingKey,msg,(message) -> {
                    //消息的属性
                    //消息的持久化属性
                    message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.fromInt(2));
                    //消息的延迟的时间的属性    毫秒
                    message.getMessageProperties().setDelay(delayTime*1000);
                    System.out.println("基于插件的延迟发消息的时间是:" + new Date());
                    return message;
                },gmallCorrelationData);
    }
}
